package com.jettech.oa.service.impl;

import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.hibernate.SessionFactory;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.taskmgmt.exe.TaskInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.jettech.oa.service.JbpmService;

/**
 * JBPM服务接口实现类
 * @author Administrator
 *
 */
@Service("jbpmService")
public class JbpmServiceImpl extends HibernateDaoSupport implements JbpmService {
	public static final String DOCUMENT_ID = "documentId";
	@Autowired
	public JbpmServiceImpl(SessionFactory sessionFactory){
		this.setSessionFactory(sessionFactory);
	}
	@Autowired
	private JbpmConfiguration jbpmConfiguration;
	private JbpmContext getJbpmContext(){
		JbpmContext context = jbpmConfiguration.createJbpmContext();
		context.setSession(this.getSession());
		return context;
	}
	public long saveProcessInstance(String processName, long documentId) {
		JbpmContext context = getJbpmContext();
		ProcessDefinition def = context.getGraphSession().findLatestProcessDefinition(processName);
		ProcessInstance instance = new ProcessInstance(def);
		instance.getContextInstance().setVariable(DOCUMENT_ID, documentId);
		context.save(instance);
		return instance.getId();
	}

	@SuppressWarnings("unchecked")
	public void deleteProcessDefinition(String processName) {
		JbpmContext context = getJbpmContext();
		List<ProcessDefinition> defs = context.getGraphSession().findAllProcessDefinitionVersions(processName);
		for(ProcessDefinition def:defs){
			context.getGraphSession().deleteProcessDefinition(def);
		}
	}

	public void deleteProcessInstance(long processInstanceId) {
		JbpmContext context = getJbpmContext();
		context.getGraphSession().deleteProcessInstance(processInstanceId);
	}

	public String saveProcessDefinition(byte[] processDefFile) {
		JbpmContext context = getJbpmContext();
		ProcessDefinition def = ProcessDefinition.parseXmlInputStream(new ByteArrayInputStream(processDefFile));
		context.deployProcessDefinition(def);
		return def.getName();
	}

	public String searchNextStep(String actorId, long processInstanceId,
			String transitionName) {
		JbpmContext context = getJbpmContext();
		ProcessInstance instance = context.getProcessInstance(processInstanceId);
        //起点名称
		String startStateName = instance.getProcessDefinition().getStartState().getName();
		//当前节点名称
		String currentNodeName = instance.getRootToken().getNode().getName();
		if(startStateName.equals(currentNodeName)){
			if(transitionName != null){
				instance.signal(transitionName);
			}else{
				instance.signal();
			}
		}else{
			List<TaskInstance> taskInstances = findTaskInstances(context,actorId);
			for(TaskInstance ti:taskInstances){
				if(processInstanceId == ti.getProcessInstance().getId()){
					if(transitionName != null){
						instance.signal(transitionName);
					}else{
						instance.signal();
					}
					break;
				}
			}
		}
		return null;
	}
	
	public List<Long> searchMyTashList(String actorId) {
		JbpmContext context = getJbpmContext();
		List<Long> docIds = new ArrayList<Long>();
		List<TaskInstance> taskInstances = findTaskInstances(context,actorId);
		for(TaskInstance ti:taskInstances){
			Long docId = (Long)ti.getProcessInstance().getContextInstance().getVariable(DOCUMENT_ID);
			docIds.add(docId);
		}
		return docIds;
	}

	@SuppressWarnings("unchecked")
	public List searchNextTransitions(String actorId, long processInstanceId) {
		JbpmContext context = getJbpmContext();
		ProcessInstance instance = context.getProcessInstance(processInstanceId);
		//起点名称
		String startStateName = instance.getProcessDefinition().getStartState().getName();
		//当前节点名称
		String currentNodeName = instance.getRootToken().getNode().getName();
		Collection<TaskInstance> nextTransititions = null;
		if(startStateName.equals(currentNodeName)){
			nextTransititions = instance.getRootToken().getAvailableTransitions();			
		}else{
			List<TaskInstance> taskInstances = findTaskInstances(context,actorId);
			for(TaskInstance ti:taskInstances){
				if(processInstanceId == ti.getProcessInstance().getId()){
					nextTransititions = ti.getAvailableTransitions();
					break;
				}
			}
		}
		List<String> transititionNames = new ArrayList<String>();
		for(TaskInstance ti:nextTransititions){
			transititionNames.add(ti.getName());
		}
		return transititionNames;
	}
	
	private List<TaskInstance> findTaskInstances(JbpmContext context,String actorId){
		List<TaskInstance> taskInstances = context.getTaskMgmtSession().findTaskInstances(actorId);
		List<TaskInstance> pooledTaskInstances = context.getTaskMgmtSession().findPooledTaskInstances(actorId);
		taskInstances.addAll(pooledTaskInstances);
		return taskInstances;
	}
}
